package com.a0soft.gphone.aTruffleHog.wnd.stat;
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 3, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * Copyright(C) 2011 
 *   Sam Lu <ysl.sam.lu (at) gmail.com>
 *
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.a0soft.gphone.aTruffleHog.R;
import com.a0soft.gphone.aTruffleHog.analytic.AnalyticsUtil;
import com.a0soft.gphone.aTruffleHog.di.DeviceInfo;
import com.a0soft.gphone.aTruffleHog.di.DeviceInfoKey;
import com.a0soft.gphone.aTruffleHog.srvc.HttpConnSrvc;
import com.a0soft.gphone.aTruffleHog.util.CONSTS;
import com.a0soft.gphone.aTruffleHog.util.MccMnc;
import com.a0soft.gphone.aTruffleHog.util.aDebug;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class TopOperatorStatsFrg extends BaseStatFragment {
    protected static int TYPE_MY_COUNTRY = 1;
    protected static int TYPE_ALL_COUNTRIES = 2;
    
    private ArrayList<TopOpData>   m_data;
    
    private static final int OTHERS_MCC_MNC = -1;
    
    private static final String LOG_TAG = TopOperatorStatsFrg.class.getSimpleName();
    
    ////////////////////////////////////////
    public static TopOperatorStatsFrg 
    NewInstance(int nType) 
    {
        TopOperatorStatsFrg frg = new TopOperatorStatsFrg();
        SetType(frg, nType);
        return frg;
    }
    
    @Override public void 
    onActivityCreated(Bundle bdSavedInstanceState)
    {
        super.onActivityCreated(bdSavedInstanceState);
        if (aDebug.ENABLED) aDebug.d(LOG_TAG, "onActivityCreated(): m_nType=" + m_nType);

        AnalyticsUtil.GetInstance(getActivity()).TrackPageView(
            m_nType == TYPE_MY_COUNTRY ? AnalyticsUtil.PAGE_STAT_TOP_OPERATOR_MY : 
                                         AnalyticsUtil.PAGE_STAT_TOP_OPERATOR_ALL);
    }
    
    @Override public View 
    onCreateView(LayoutInflater inflater, ViewGroup vgContainer,
                 Bundle bdSavedInstanceState) 
    {
        View vRoot = super.onCreateView(inflater, vgContainer, bdSavedInstanceState);
        
        if (!getActivity().isFinishing())
            _GetTopOperatorStats(false);
        
        return vRoot;
    }
    
    private void
    _SetData(JSONObject json)
    {
        try {
            m_lDataTime = json.getLong("t");
            
            JSONArray data = json.getJSONArray("d");
            final int N = data.length();
            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "N=" + N);
            
            if (N <= 0) {
                m_data = new ArrayList<TopOpData>(1);
            }
            else {
                m_data = new ArrayList<TopOpData>(N);
                for (int i = 0; i < N; i++) {
                    JSONObject obj = data.getJSONObject(i);
                    TopOpData op = new TopOpData();
                    op.m_fPercentage = (float)obj.getDouble("p");
                    op.m_lCount = obj.getLong("c");
                    op.m_nMCC = obj.getInt("mc");
                    op.m_nMNC = obj.getInt("mn");
                    //aDebug.d(LOG_TAG, "count=" + op.m_lCount + ", per=" + op.m_fPercentage);
                    aDebug.d(LOG_TAG, "mcc=" + op.m_nMCC + ", mnc=" + op.m_nMNC);
                    
                    m_data.add(op);
                }
            }
        }
        catch (JSONException e) {
            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "_SetData()", e);
            m_data = new ArrayList<TopOpData>(1);
        }
        SetStatData(m_data);
        
        Context ctx = getActivity();
        if (ctx == null) return;

        _AddFakeData(ctx);
        _MergeData(ctx);
        _SortData();
        
        DeviceInfo di = DeviceInfo.GetInstance(ctx);  
        int nMCC = di.GetInt(DeviceInfoKey.K.TP_SIM_MCC);
        int nMNC = di.GetInt(DeviceInfoKey.K.TP_SIM_MNC);
        m_strMy = getString(R.string.top_operator_of_your_device, 
                            MccMnc.GetNetworkName(ctx, nMCC, nMNC));
        
        m_nMyIdx = -1;
        final int N = m_data.size();
        for (int i = 0; i < N; i++) {
            TopOpData op = m_data.get(i);
            if (op.m_nMCC == nMCC && op.m_nMNC == nMNC) {
                m_nMyIdx = i;
                break;
            }
        }
        if (m_nMyIdx == -1) {
            //find others
            for (int i = N - 1; i >= 0; i--) {
                TopOpData op = m_data.get(i);
                if (op.m_nMCC == OTHERS_MCC_MNC) {
                    m_nMyIdx = i;
                    break;
                }
            }
        }
        
        SetDataFinished();
    }
    
    private void
    _SortData()
    {
        if (m_data.size() <= 1)
            return;
        
        Collections.sort(m_data, new Comparator<TopOpData>() {
            @Override public int 
            compare(TopOpData op1, TopOpData op2)
            {
                if (op1.m_nMCC == OTHERS_MCC_MNC)
                    return 1;
                if (op2.m_nMCC == OTHERS_MCC_MNC)
                    return -1;
                
                float f = op2.m_fPercentage - op1.m_fPercentage;
                if (f < 0) return -1; else if (f > 0) return 1;
                int n = op2.m_nMCC - op1.m_nMCC;
                if (n != 0) return n;
                return op2.m_nMNC - op1.m_nMNC;
            }
        });
    }
    
    private void
    _MergeData(Context ctx)
    {
        final int N = m_data.size();
        float fMinPercentage = Float.NaN;
        if (N > CONSTS.MAX_PIE_NUMBER) { 
            float[] fPercentages = new float[N];
            for (int i = 0; i < N; i++) {
                TopOpData op = m_data.get(i);
                fPercentages[i] = op.m_fPercentage;
            }
            Arrays.sort(fPercentages);
            fMinPercentage = fPercentages[N - CONSTS.MAX_PIE_NUMBER + 1];
            if (fMinPercentage < CONSTS.MIN_PIE_PERCENTAGE) {
                fMinPercentage = CONSTS.MIN_PIE_PERCENTAGE;
            }
        }
        else {
            for (TopOpData op: m_data) {
                if (op.m_fPercentage < CONSTS.MIN_PIE_PERCENTAGE) {
                    fMinPercentage = CONSTS.MIN_PIE_PERCENTAGE;
                    break;
                }
            }
        }
        if (Float.isNaN(fMinPercentage)) return;
        
        //find others and create if not exist
        TopOpData opOthers = null;
        for (TopOpData op: m_data) {
            if (op.m_nMCC == OTHERS_MCC_MNC) {
                opOthers = op;
                break;
            }
        }
        if (opOthers == null) {
            opOthers = new TopOpData();
            opOthers.m_fPercentage = 0;
            opOthers.m_lCount = 0;
            opOthers.m_nMCC = OTHERS_MCC_MNC;
            opOthers.m_nMNC = OTHERS_MCC_MNC;
            
            m_data.add(opOthers);
        }
        
        //merge
        ArrayList<TopOpData> tdToBeRemoved = new ArrayList<TopOpData>();
        for (TopOpData op: m_data) {
            if (op.m_nMCC != OTHERS_MCC_MNC) {
                if (op.m_fPercentage < fMinPercentage) {
                    opOthers.m_fPercentage += op.m_fPercentage;
                    opOthers.m_lCount += op.m_lCount;
                    tdToBeRemoved.add(op);
                }
            }
        }
        m_data.removeAll(tdToBeRemoved);
    }
    
    private void
    _AddFakeData(Context ctx)
    {        
        DeviceInfo di = DeviceInfo.GetInstance(ctx);
        final int nMCC = di.GetInt(DeviceInfoKey.K.TP_SIM_MCC);
        final int nMNC = di.GetInt(DeviceInfoKey.K.TP_SIM_MNC);
        
        //no stats, add current device info
        if (m_data.size() == 0) { 
            m_lDataTime = System.currentTimeMillis();
            
            TopOpData op = new TopOpData();
            op.m_lCount = 1;
            op.m_fPercentage = 1f;
            op.m_nMCC = nMCC;
            op.m_nMNC = nMNC;
            
            m_data.add(op);
        }
        
        //only one stat, add others
        if (m_data.size() == 1) { //get 1%
            TopOpData tdOnlyOne = m_data.get(0);
            long lTotal = tdOnlyOne.m_lCount;
            
            TopOpData td = new TopOpData();
            td.m_fPercentage = tdOnlyOne.m_fPercentage * 0.01f;
            td.m_lCount = Math.max(1, (long)(lTotal * 0.01f));
            td.m_nMCC = OTHERS_MCC_MNC;
            td.m_nMNC = OTHERS_MCC_MNC;
            
            m_data.add(td);
            
            tdOnlyOne.m_fPercentage -= td.m_fPercentage;
            tdOnlyOne.m_lCount -= td.m_lCount;
        }

        //add one if no current device info
        if (nMCC != 0 && nMNC != 0) {
            boolean bHasMyDeviceInfo = false;
            long lMaxCount = Long.MIN_VALUE;
            TopOpData tdMax = null;
            for (TopOpData op: m_data) {
                if (!bHasMyDeviceInfo && 
                    op.m_nMCC == nMCC && op.m_nMNC == nMNC) {
                    bHasMyDeviceInfo = true;
                }
                if (lMaxCount < op.m_lCount) {
                    lMaxCount = op.m_lCount;
                    tdMax = op;
                }
            }
            if (!bHasMyDeviceInfo) { //get 10% from max os
                m_lDataTime = System.currentTimeMillis();
                
                TopOpData op = new TopOpData();
                op.m_fPercentage = tdMax.m_fPercentage * 0.1f;
                op.m_lCount = Math.max(1, (long)(lMaxCount * 0.1f));
                op.m_nMCC = nMCC;
                op.m_nMNC = nMNC;
                
                m_data.add(op);
                
                tdMax.m_fPercentage -= op.m_fPercentage;
                tdMax.m_lCount -= op.m_lCount;
            }
        }
    }
    
    private void
    _GetTopOperatorStats(boolean bRedownloadFromServer)
    {
        Context ctx = getActivity();
        
        DeviceInfo di = DeviceInfo.GetInstance(ctx);
        final String strDID = di.GetString(DeviceInfoKey.K.UR_ID);
        
        if (m_nType == TYPE_MY_COUNTRY) {
            final String strCountry = di.GetString(DeviceInfoKey.K.UR_COUNTRY);
            HttpConnSrvc.RequestTopOperatorOfMyCntyStats(ctx, strCountry, strDID, bRedownloadFromServer);     
        }
        else if (m_nType == TYPE_ALL_COUNTRIES) {
            HttpConnSrvc.RequestTopOperatorOfWorldStats(ctx, strDID, bRedownloadFromServer);  
        }
    }

    @Override protected boolean 
    IsMyDownloadCmd(int nCmd)
    {
        if (m_nType == TYPE_MY_COUNTRY)
            return (nCmd == HttpConnSrvc.CMD_GET_TOP_OPERATOR_STATS_MY);
        else if (m_nType == TYPE_ALL_COUNTRIES)
            return (nCmd == HttpConnSrvc.CMD_GET_TOP_OPERATOR_STATS_ALL);
        return false;
    }
    
    @Override protected void 
    OnMyDownloadSuccess(int nCmd, JSONObject json)
    {
        super.OnMyDownloadSuccess(nCmd, json);
        
        _SetData(json);
    }
    
    @Override protected void
    SetListItemView(StatData stat, ListItemTagData tag)
    {
        TopOpData op = (TopOpData)stat;
        
        Context ctx = getActivity();
        
        if (op.m_nMCC != OTHERS_MCC_MNC && op.m_nMNC != OTHERS_MCC_MNC) {
            tag.m_tvVersion.setText(ctx.getString(R.string.mcc_mnc_title, 
                                                  MccMnc.GetNetworkName(ctx, op.m_nMCC, op.m_nMNC)));
            tag.m_tvAPI.setText(ctx.getString(R.string.mcc_mnc_code, 
                                              op.m_nMCC, op.m_nMNC,
                                              MccMnc.GetCountryName(ctx, op.m_nMCC)));
        }
        else {
            tag.m_tvVersion.setText(R.string.others);
            tag.m_tvAPI.setText("");
        }
    }
    
    ////////////////////////////////////
    private static class TopOpData extends StatData {
        private int m_nMCC;
        private int m_nMNC;
    }
}
